package home1ess.passport.handler;

import common.exception.ServiceException;
import common.web.JsonResult;
import common.web.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理 MethodArgumentNotValidException
     * 让客户端知道出了什么异常 验证相关的异常,客户端可以基于异常,进行下一步的处理
     * @param e
     * @return
     */
    @ExceptionHandler
    public JsonResult
    handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
        log.error("捕获MethodArgumentNotValidException",e);
        //String message = e.getMessage();
        List<FieldError> fieldErrors = e.getFieldErrors();
        StringBuffer allMessage = new StringBuffer();
        for (FieldError fieldError : fieldErrors) {
            String defaultMessage = fieldError.getDefaultMessage();
            allMessage.append(defaultMessage);
            allMessage.append(",");
        }
        //System.out.println(e.getFieldError());
        //System.out.println(message);
        return JsonResult.fail(StatusCode.BAD_REQUEST.getCode(),
                deleteLastChar(allMessage));
    }

    /**
     * 类别名称不能太长,类别名称不能为空,
     * 变成
     * 类别名称不能太长,类别名称不能为空
     *
     * 1 从0开始截取到最后一位减1
     * 2 删除最后一位
     *
     * @param str
     * @return
     */
    private String deleteLastChar(StringBuffer str){
        //StringBuffer 线程安全  synchronized 关键字
        //StringBuilder 线程不安全
        StringBuffer delete = str.delete(str.lastIndexOf(","), str.length());
        return delete.toString();
    }

    /**
     * 处理运行时异常
     * @param e
     * @return
     */
    @ExceptionHandler
    public JsonResult handleRuntimeException(RuntimeException e){
        log.error("捕获运行时异常",e);
        return JsonResult.fail(StatusCode.ERROR.getCode(), e.getMessage());
    }

    /**
     * 处理自定义业务异常
     * @param e
     * @return
     */
    @ExceptionHandler
    public JsonResult handleServiceException(ServiceException e){
        log.error("捕获自定义业务异常",e);
        return JsonResult.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler
    public JsonResult handleIllegalArgumentException(IllegalArgumentException e){
        log.error("捕获IllegalArgumentException",e);
        return JsonResult.fail(StatusCode.BAD_REQUEST.getCode(), e.getMessage());
    }

    @ExceptionHandler
    public JsonResult handleBindException(BindException e){
        log.error("捕获验证框架异常",e);

        List<FieldError> fieldErrors = e.getFieldErrors();
        StringBuffer stringBuffer=new StringBuffer();
        for (FieldError fieldError : fieldErrors) {
            String defaultMessage = fieldError.getDefaultMessage();
            stringBuffer.append(defaultMessage);
            stringBuffer.append(",");
        }
        StringBuffer delete = stringBuffer.deleteCharAt(stringBuffer.length()-1);
        return JsonResult.fail(StatusCode.BAD_REQUEST.getCode(),
                delete.toString());
    }

    /**
     * 不能预见什么时候会抛出运行时异常
     * 数据库连接失败,这种异常是不能给客户端, 客户端不能处理数据库异常
     * 兜底
     * @param throwable
     * @return
     */
    @ExceptionHandler
    public JsonResult handleException(Throwable throwable) {
        log.error("系统出现异常",throwable); //我们开发人员要关注,通过日志快速的定位问题,修复问题.
        return JsonResult.fail(StatusCode.ERROR.getCode(),"网络波动,请稍后再试!!!");//给用户看到
    }

}
